/*
 * bots.cpp
 *
 *  Created on: Nov 16, 2013
 *      Author: killerg
 */
#include "robot_deps.h"
#include "bots.h"
#include "bot.h"

#include "share/cfg_file.h"
#include "share/clock.h"
#include "share/util.h"
#include "share/msg_coder.h"

#include "version.h"

#include <event2/event.h>
#include <string.h>

bots_t g_bots;

bool bots_t::init(int botnum, int startid, const char* prefix, int totalnum) {
    code_cb = NULL;
    cfg = new cfg_file_t;
    if (!cfg->load("robot.txt", prefix))
        return false;

    clock = new my_clock_t;
    clock->init(100);

    base = event_base_new();
    this->botnum = botnum;
    this->startid = startid;
    this->totalnum = totalnum;
    if (totalnum < botnum) {
    	totalnum = botnum;
    }

    if (botnum <= 0 || startid < 0)
        return false;

    bots = new bot_t[botnum];
    max_conning = g_bots.cfg->get_int("max_conning", 10);

    arg_t arg;
    arg.min_interval = g_bots.cfg->get_int("min_interval", 1000);
    arg.max_interval = g_bots.cfg->get_int("max_interval", 20000);
    arg.min_packet = g_bots.cfg->get_int("min_packet", 10);
    arg.max_packet = g_bots.cfg->get_int("max_packet", 4000);
    arg.min_play_sec = g_bots.cfg->get_int("min_play_sec", 36000000);
    arg.max_play_sec = g_bots.cfg->get_int("max_play_sec", 36000000);
    arg.logon_addr = fmt_cstr("%s:%d", cfg->get_str("logon_ip").c_str(), cfg->get_int("logon_port"));
    arg.base = base;
    if (g_bots.cfg->get_bool("encode_server", false)) {
        if (init_code_table()) {
            this->code_cb = encmsg;
        }
    }

    for (int i=0; i<totalnum; ++i) {
    	account_t* account = new account_t;
    	account->account = fmt_str("r%lld", startid + i);
        account->id = startid + i;
        account->passwd = Md5(account->account.c_str());

        accounts.push(account);
    }


    for (int i=0; i<botnum; ++i) {
        if (!bots[i].init(arg)) {
            return false;
        }
    }

    timer = 0.0f;

    remain_conning = max_conning;
    last_conning = 0;

    return true;
}

void bots_t::destroy() {
    for (int i=0; i<botnum; ++i) {
        bots[i].destroy();
    }
    safe_del_array(bots);

    if (NULL != base)
        event_base_free(base);

    clock->destroy();
    safe_del(clock);

    safe_del(cfg);

    if (code_cb) {
        destroy_code_table();
        code_cb = NULL;
    }
}

std::string bots_t::get_str() {
    std::stringstream ss;
    for (int i=0; i<ESSTAGENUM; ++i) {
        char buffer[100];
        sprintf(buffer, "%s:%-4d ", ServerStageName[i], count[i]);
        ss << buffer;
    }
    return ss.str();
}

void bots_t::loop() {
    while (true) {
        memset(count, 0, sizeof(count));
        clock->begin_update();
        remain_conning = max_conning - last_conning;
        for (int i=0; i<botnum; ++i) {
            bots[i].update();
            ++count[bots[i].stage];
        }
        last_conning = count[ELogonConnecting];
        clock->end_update();
        event_base_loop(base, EVLOOP_NONBLOCK);
        clock->wait_frame();

        timer += g_bots.clock->delta;
        if (timer >= 1.0f) {
            if (g_bots.botnum > 1) {
                printf("num:%d %s\n", botnum, get_str().c_str());

            } else if (g_bots.botnum == 1) {
                auto bot = g_bots.bots;
                printf("stage:%s %s\n", ServerStageName[bot->stage], bot->stat.get_str().c_str());
                bot->stat.reset();
            }

            timer = 0.0f;
        }
    }
}
